#!/usr/bin/perl -I ./thirds
# Author: lilongen (microli@sz.webex.com, lonli@cisco.com, lilongen@163.com)
# Date: 05/18/2007
#
package Assistor;


use strict;
use English;
use XML::Simple;
use Data::Dumper;
use File::Iterator;

#===============================================================================
# CONSTRUCTOR:	
#       default config file: config.xml
#       $obj = new Assistor; 
#		$obj = new Assistor($config_file_name);
#===============================================================================
sub new() {
    my $pkg = shift;
    my $config_file = shift;
    
    my $self = {};
    bless $self, $pkg;
    
    $self->get_config_files();
    
    if (!defined($config_file) || $config_file eq "") {
       $config_file = $self->{DEFAULT_CFG};
    } else {
    	if (!$self->isValidCfg($config_file)) {
    		$config_file = $self->{DEFAULT_CFG};
    	}
    }
    $config_file = "config/$config_file";    
    
    $self->{'CONFIG_FILE'} = $config_file;
    $self->{'CCV_CFG'} = "config/ccv.cfg";
    $self->{'PROG_LANGS'} = "config/program.lang";
    $self->{'LOG_ANALYSER'} = "analyse.cvs.log.pl";
    $self->{'DIFF_ANALYSER'} = "analyse.cvs.rdiff.pl";
    $self->{'SVN_DIFF_ANALYSER'} = "analyse.svn.diff.pl";
    $self->{'SVN_LOG_ANALYSER'} = "analyse.svn.log.pl";
    $self->{'SVN_DIFF_ANALYSER'} = "analyse.svn.diff.pl";
    $self->{'SVN_LOG_PARSED_INFO_FILE_NAME'} = "log.parsed.info"; 
    
    $self->{'brief_report'} = "brief_report.csv";
    
    $self->{'all_modules_brief_report'} = "all_modules_brief_report.csv";
    
    $self->{'log_ext'} = ".log";
    $self->{'diff_ext'} = ".diff";
    
    $self->{'ALL_MODULES_SUM_INFO_FILE'} = "all_modules_sum_info";

    
    my $time_snapshot = shift;

    if (defined($time_snapshot) && !($time_snapshot eq "")) {
		$time_snapshot =~ s/ /\+/;    
		$self->{'time'} = $time_snapshot;
		$self->split_time();
    } else {
		$self->format_time();
    }
 
    return $self;
}

sub set_config_file() {
	my $self = shift;
	my $cfg = shift;
	
	$self->{'CONFIG_FILE'} = "config/$cfg";
}

sub set_time_snap() {
	my $self = shift;
	my $time_snapshot = shift;
	
	$self->{'time'} = $time_snapshot;
	$self->split_time();	
}

sub save_ccv_cfg() {
    my $self = shift;
	my $cfgs = shift;
	
    if (!open(CCV_CFG, ">", $self->{CCV_CFG})) {
		output("Can not create/open $self->{CCV_CFG}!\n");
		
		return 1;
	} 		
	
	while ( my ($key, $value) = each(%$cfgs) ) {
        print CCV_CFG "$key=$value\n";
    }	
    
    close CCV_CFG;		
}

sub get_ccv_cfg() {
	my $self = shift;

	my $cfg = {};
    if (!open(CCV_CFG, "<", $self->{CCV_CFG})) {
		output("Can not create/open $self->{CCV_CFG}!\n");
		
		return $cfg;
	} 		
	
	my $line = "";
	while (1) {
		$line = <CCV_CFG>;
		if (!defined($line)) {
			last;
		}
		
		if ($line =~ m/^(.+)=(.*)$/) {
			$cfg->{$1} = $2;	
		}
	}
		
	$self->{ccv_cfg} = $cfg;
	
	return $cfg;
}

sub get_module_info_by_module_id() {
    my $self = shift;
    my $module_id = shift;
  	my $modules = $self->{modules};
    for (my $i = 0; $i <= $#{$modules}; $i++) {
        if ($modules->[$i]->{id} eq $module_id) {
            return $modules->[$i];   
        }
    }
    
    return undef;
}

sub get_date() {
    my $self = shift;
    my $date_string = shift;
    
    return substr($date_string, 0, index($date_string, " "));
}

sub getModules() {
    my $self = shift;
    my $xml = new XML::Simple(ForceArray => 1);
    my $config = $xml->XMLin($self->{'CONFIG_FILE'});

    my $G_CFG = {};
    $G_CFG->{cvsId}     = $self->get_value($config->{cvs_account_id}, "");
    $G_CFG->{cvsPw}     = $self->get_value($config->{cvs_account_pw}, "");
    $G_CFG->{cvsMode}   = $self->get_value($config->{cvs_access_mode}, "pserver");
    $G_CFG->{svnId}     = $self->get_value($config->{svn_account_id}, "");
    $G_CFG->{svnPw}     = $self->get_value($config->{svn_account_pw}, "");
    $G_CFG->{svnMode}   = $self->get_value($config->{svn_access_mode}, "svn");
    $G_CFG->{file_filter} = $self->get_value($config->{file_filter}, ".*");
    
    my $modules = [];
    my $modules4UI = [];
    my $cnt = $#{$config->{module}};
    for (my $i = 0; $i<= $cnt; $i++) {
        my $module = {};
        $module->{id}           = $self->get_value($config->{module}->[$i]->{id}, "");
        $module->{type}         = $self->get_value($config->{module}->[$i]->{type}, "cvs");
        $module->{module}       = $self->get_value($config->{module}->[$i]->{module}, "");
        $module->{server}       = $self->get_value($config->{module}->[$i]->{server}, "");
        $module->{repository}   = $self->get_value($config->{module}->[$i]->{repository}, "");
		
		$module->{username} 			= $self->get_value($config->{module}->[$i]->{account_id},   ($module->{type} eq "cvs" ? $G_CFG->{cvsId} : $G_CFG->{svnId}));
       	$module->{password} 			= $self->get_value($config->{module}->[$i]->{account_pw},   ($module->{type} eq "cvs" ? $G_CFG->{cvsPw} : $G_CFG->{svnPw}));				
        $module->{access_mode} 			= $self->get_value($config->{module}->[$i]->{access_mode},  ($module->{type} eq "cvs" ? $G_CFG->{cvsMode} : $G_CFG->{svnMode}));					
        
        $module->{file_filter} 			= $self->get_value($config->{module}->[$i]->{file_filter}, 	$G_CFG->{file_filter});					
        
        $module->{viewvc_entry} 		= $self->get_value($config->{module}->[$i]->{viewvc_entry}, "");					
        $module->{viewvc_repository} 	= $self->get_value($config->{module}->[$i]->{viewvc_repository}, "");					

        $module->{repository_mapping} 	= $self->get_value($config->{module}->[$i]->{repository_mapping}, "");

        $module->{log}          		= $config->{module}->[$i]->{id}->[0] . $self->{log_ext};
        $module->{diff}         		= $config->{module}->[$i]->{id}->[0] . $self->{diff_ext};
        if (uc($module->{type}) eq "SVN") {
        	$module->{trunk_directory}  = $config->{module}->[$i]->{trunk_directory}->[0] . "/" . $module->{module};
        	$module->{branch_directory} = $config->{module}->[$i]->{branch_directory}->[0] . "/%s/" . $module->{module};
        	$module->{tag_directory}    = $config->{module}->[$i]->{tag_directory}->[0] . "/%s/" . $module->{module};
        }
        
        push @{$modules}, $module;

        my $module4UI = {};        
        $module4UI->{id} 			= $module->{id};
        $module4UI->{type} 			= $module->{type};
        $module4UI->{module} 		= $module->{module};
        $module4UI->{server} 		= $module->{server};
        $module4UI->{repository} 	= $module->{repository};
        $module4UI->{access_mode} 	= $module->{access_mode};
        if (uc($module->{type}) eq "SVN") {
        	$module4UI->{trunk_directory} =  $module->{trunk_directory};
        	$module4UI->{branch_directory} =  $module->{branch_directory};
        	$module4UI->{tag_directory} =  $module->{tag_directory};

        	$module4UI->{trunkFullPath} =  $self->get_svn_module_url($module, "", "trunk");
        	$module4UI->{branchFullPath} =  $self->get_svn_module_url($module, "%s", "branch");
        	$module4UI->{tagFullPath} =  $self->get_svn_module_url($module, "%s", "tag");
        } else {
        	$module4UI->{repositoryPath}= $self->get_module_cvsroot_without_uid($module4UI);	
        }
       
        push @{$modules4UI}, $module4UI;
    }

    $self->{modules} = $modules;
    $self->{modules4UI} = $modules4UI;

    return $self->{modules};
}


sub get_program_langs() {
    my $self = shift;
    my $xml = new XML::Simple();
    my $langs = $xml->XMLin($self->{PROG_LANGS});

    return $langs;
}

sub get_program_langs_ext() {
    my $self = shift;

    my $cfg = $self->get_program_langs();
    my $langs = {
    	name => "",
    	ext => "",
    	code => {
    		name => "",
    		ext => ""
    	},
    	
    	configure => {
    		name => "",
    		ext => ""
    	},
    	
    	other => {
    		name => "",
    		ext => ""
    	}    	
    };
    
    while ( my($key, $val) = each(%{$cfg->{lang}}) ) {
		$langs->{name} .= $key . " ";
		$langs->{ext} .= $val->{ext} . " ";
		
		if ($val->{type} eq "code") {
			$langs->{code}->{name} .=  $key . " ";
			$langs->{code}->{ext} .=  $val->{ext} . " ";
		} elsif ($val->{type} eq "configure") {
			$langs->{configure}->{name} .=  $key . " ";
			$langs->{configure}->{ext} .=  $val->{ext} . " ";			
		} else {
			$langs->{other}->{name} .=  $key . " ";
			$langs->{other}->{ext} .=  $val->{ext} . " ";					
		}
	}
	
	return $langs;
}

sub get_value() {
    my $self 		= shift;
    my $moduleCfg 	= shift;
    my $default 	= shift;
	
	my $ret = $default;	
    if (defined($moduleCfg)) {
    	if ((ref($moduleCfg) eq "ARRAY") && (ref($moduleCfg->[0]) ne "HASH")) {
    		$ret = $moduleCfg->[0];
    	} else {
    		$ret = "";
    	}
    }
    
    return $ret;
}

sub get_report_template_name() {
    my $self = shift;
    my $flag = shift;
    if ($flag eq "top") {
        return "users_details_top.html";
    } elsif ($flag eq "main") {
        return "users_details_main.html";
    } elsif ($flag eq "diff_main") {
        return "diff_main.html";        
    } elsif ($flag eq "file_main") {
        return "files_details_main.html";        
    } elsif ($flag eq "diff_group") {
    	return "diff_group_main.html";
    } elsif ($flag eq "diff_flat") {
    	return "diff_flat_main.html";    
	} elsif ($flag eq "diff_top") {
    	return "diff_top.html";    
	} elsif ($flag eq "diff_frames") {
    	return "diff.html";    
	} elsif ($flag eq "LOG_TPL") {
    	return "log_report.html";    
	} elsif ($flag eq "DIFF_TPL") {
    	return "diff_report.html";    
	}  else {
        return "users_details.html";
    }
}

sub get_report_template_file() {
    my $self = shift;
    my $flag = shift;
    
    return "web/" . $self->get_report_template_name($flag);    
}

sub path() {
    my $self = shift;
    my $full_flag = shift;
    my $full_path = "web/reports/" . $self->{'date'} . "/" . $self->{'serial'} . "/";
    if (defined($full_flag) && $full_flag == 0) {
        $full_path = "";
    }
    
    return $full_path;   
}

sub webpath() {
    my $self = shift;

    my $full_path = "ccv/reports/" . $self->{'date'} . "/" . $self->{'serial'} . "/";
    
    return $full_path;   
}

sub get_branch_module_11_file_operat_webpath() {
    my $self = shift;
    my $branch = shift;
    my $module_id = shift;    
	my $file = shift;
    my $full_path = "/ccv/operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/" . $branch . "/" . $module_id . "/1.1/". $file;
    
    return $full_path;   
}

sub get_branch_module_mfi_url() {
    my $self = shift;
    my $branch = shift;
    my $module_id = shift;    
    my $full_path = "/ccv/" . $self->get_branch_module_mfi($branch, $module_id);
    
    return $full_path;   
}

sub get_branch_module_mfi() {
    my $self = shift;
    my $branch = shift;
    my $module_id = shift;    
    my $full_path = "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/" . $branch . "/" . $module_id . "/head/__CCV_MODULE_FILES_INFO";
    
    return $full_path;   
}

sub get_branch_report_file() {
    my $self = shift;
    my $branch = shift;
    my $path_falg = shift;
    
    if (defined($path_falg) && $path_falg == 0) {
        return $branch . "-" . $self->get_report_template_name("");    
    } else {
        return $self->path(shift) . $branch . "-" . $self->get_report_template_name("");    
    }
}

sub get_rdiff_report_file() {
    my $self = shift;
    my $branch = shift;
    my $path_falg = shift;
    
    if (defined($path_falg) && $path_falg == 0) {
        return $branch . "-" . $self->get_report_template_name("");    
    } else {
        return $self->path(shift) . $branch . "-" . $self->get_report_template_name("diff_frames");    
    }
}

sub get_branch_report_top_file() {
    my $self = shift;
    my $branch = shift;
    
    return $self->path(shift) . $branch . "-" . $self->get_report_template_name("top");    
}

sub get_rdiff_report_top_file() {
    my $self = shift;
    my $branch = shift;
    
    return $self->path(shift) . $branch . "-" . $self->get_report_template_name("diff_top");    
}

sub get_branch_module_report_main_user_file() {
    my $self = shift;
    my $branch = shift;
    my $module_id = shift;
    
    return $self->path(shift) . $branch . "-" . $module_id . "-" . $self->get_report_template_name("main");
}

sub get_svn_branch_module_report_main_user_file() {
    my $self = shift;
    my $branch = shift;
    my $module_id = shift;
    
    return $self->path(shift) . $branch . "-" . $module_id . "-user_" . $self->get_report_template_name("LOG_TPL");
}

sub get_branch_module_report_main_file_file() {
    my $self = shift;
    my $branch = shift;
    my $module_id = shift;
    
    return $self->path(shift) . $branch . "-" . $module_id . "-" . $self->get_report_template_name("file_main");
}

sub get_svn_branch_module_report_main_file_file() {
    my $self = shift;
    my $branch = shift;
    my $module_id = shift;
    
    return $self->path(shift) . $branch . "-" . $module_id . "-file_" . $self->get_report_template_name("LOG_TPL");
}


sub get_rdiff_module_report_main_group_file() {
    my $self = shift;
    my $revs_dates = shift;
    my $module_id = shift;
    
    return $self->path(shift) . $revs_dates . "-" . $module_id . "-" . $self->get_report_template_name("diff_group");
}


sub get_rdiff_module_report_main_flat_file() {
    my $self = shift;
    my $revs_dates = shift;
    my $module_id = shift;
    
    return $self->path(shift) . $revs_dates . "-" . $module_id . "-" . $self->get_report_template_name("diff_flat");
}

sub get_branch_module_log_file() {
    my $self = shift;
    my $branch = shift;
    my $module_log = shift;
    
    my $log_file = "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/" . $branch . "/" . $module_log;  
    
    return $log_file;         
}

sub get_branch_module_all_df_file() {
    my $self = shift;
    my $branch = shift;
    my $mInfo = shift;
    
    my $df_file = "operate/$self->{date}/$self->{serial}/$branch/$mInfo->{id}/all.revs.df";
    
    return $df_file;         
}

sub get_branch_module_rev_files_operate_path() {
    my $self = shift;
    my $branch = shift;
    my $module_id = shift;
   
    my $path = "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/" . $branch . "/" . $module_id . "/rev_files";  
    
    return $path;
}

sub get_branch_module_file_diff_out_file() {
    my $self = shift;
    my $branch = shift;
    my $module_id = shift;
    my $file = shift;
    my $rev1 = shift;
    my $rev2 = shift;
    
    $file =~ s|/|\.|g;
    
    my $diff_out_file = "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/" . $branch . "/" . $module_id . "/" . $file . "+" . $rev1 . "+" .  $rev2;  
    
    return $diff_out_file;         
}

sub get_all_modules_sum_info_file() {
    my $self = shift;
    
    return  "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/" . $self->{'ALL_MODULES_SUM_INFO_FILE'};         
}

sub get_revisions_module_diff_file() {
    my $self = shift;
    my $revisions = shift;
    my $module_diff = shift;
    
    my $diff_file = "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/" . $revisions . "/" . $module_diff;
    return $diff_file;
}

#all modules brief txt report functions
sub get_brief_report_file() {
    my $self = shift;
    
    return $self->path(shift) . $self->{'brief_report'};    
}

sub get_brief_report_url() {
    my $self = shift;
    
    return "/" . $self->webpath() . $self->{'brief_report'};    
}

sub get_all_modules_brief_report_file() {
    my $self = shift;
    
    return $self->path(shift) . $self->{'all_modules_brief_report'};    
}

sub get_all_modules_brief_report_url() {
    my $self = shift;
    my $branch = shift;
    
    return "/" . $self->webpath() . $self->{'all_modules_brief_report'};    
}
#End

#module brief txt report functions
sub get_module_brief_report_file() {
    my $self = shift;
    my $moduleId = shift;
    
    return $self->path(shift) . $moduleId . "-" . $self->{'brief_report'};    
}


sub get_module_brief_report_url() {
    my $self = shift;
    my $moduleId = shift;
    
    return "/" . $self->webpath() . $moduleId . "-" . $self->{'brief_report'};    
}
#End


sub get_branch_html_report_url() {
    my $self = shift;
    my $branch = shift;
    
    return "/" . $self->webpath() . $branch . "-" . $self->get_report_template_name("");    
}

sub get_rdiff_html_report_url() {
    my $self = shift;
    my $revs_dates = shift;
    
    return "/" . $self->webpath() . $revs_dates . "-" . $self->get_report_template_name("diff_frames");    
}

sub get_operate_log_file() {
    my $self = shift;
    
    return "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/operate.log";
}

sub get_operate_pms_file() {
    my $self = shift;
    
    return "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/pms.ccv";	
}

sub get_operate_cvs_task_queue_file() {
    my $self = shift;
    
    return "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/tasks.queue";
}

sub get_operate_revs_dates_dir_name() {
	my $self = shift;
	my $pms = shift;
	
	my $ret = "";
	if ($pms->{mode} == 0) {
    	$ret = $pms->{rev};
    } else {
    	if ($pms->{dfRevs} ne "") {
    		$ret = $pms->{dfRevs};
    	} else {
    		$ret = $pms->{dfDates};
    	}
    }
    
    return $ret;
}

sub set_diff_revs_dates() {
	my $self = shift;
	my $pms = shift;
	
	if ($pms->{mode} == 1) {
		$pms->{dfRevs} = "";
		if ($pms->{r1} ne "" || $pms->{r2} ne "") {
			if ($pms->{r1} ne "" && $pms->{r2} ne "") {
				$pms->{dfRevs} = "$pms->{r1}-$pms->{r2}"	
			} else {
				$pms->{dfRevs} = ($pms->{r1} ne "" ? $pms->{r1} : $pms->{r2});
			}
		}
		
		$pms->{dfDates} = "";
		if ($pms->{d1} ne "" || $pms->{d2} ne "") {
			if ($pms->{d1} ne "" && $pms->{d2} ne "") {
				$pms->{dfDates} = "$pms->{d1}-$pms->{d2}"	
			} else {
				$pms->{dfDates} = ($pms->{d1} ne "" ? $pms->{d1} : $pms->{d2});
			}
			
			$pms->{dfDates} =~ s|/|\-|g;
		}		
	}
}

sub ccv_log() {
    my $self = shift;
    my $logInfo = shift;
    
    my $LOG;
    if (!open($LOG, ">>", $self->get_operate_log_file())) {
       return 1;
    }
    print $LOG $logInfo . "\n";
    close($LOG);     
}

sub get_module_co_11_file() {
	my $self = shift;
	my $branch = shift;
	my $module_id = shift;
	my $file = shift;
	
	return $self->get_module_co_11_path($branch, $module_id) . $file;
}

sub get_module_co_head_file() {
	my $self = shift;
	my $branch = shift;
	my $module_id = shift;
	my $file = shift;

	return $self->get_module_co_head_path($branch, $module_id) . $file;
}

sub get_module_co_11_path() {
	my $self = shift;
	my $branch = shift;
	my $module_id = shift;
	
	return "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/" . $branch . "/" . $module_id . "/1.1/";
}

sub get_module_co_head_path() {
	my $self = shift;
	my $branch = shift;
	my $module_id = shift;
	
	return "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/" . $branch . "/" . $module_id . "/head/";
}

sub get_module_operate_path() {
	my $self = shift;
	my $branch = shift;
	my $module_id = shift;
	
	return "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/" . $branch . "/" . $module_id . "/";
}

sub get_operate_path() {
	my $self = shift;
	my $branch = shift;
	
	return "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/" . $branch . "/";
}

sub get_report_log_file() {
    my $self = shift;
    
    return "operate/ccv.log";
}

sub get_wids_file() {
    my $self = shift;
    
    return "config/accounts";
}

sub get_time_snapshot() {
    my $self = shift;
    
    return $self->{'time'};
}

sub get_time_date() {
    my $self = shift;
    
    return $self->{'date'};
}

sub get_time_serial() {
    my $self = shift;
    
    return $self->{'serial'};
}

sub get_friendly_time() {
    my $self = shift;
    
    return $self->{'friendly_time'};
}

sub log_ccv_query() {
	my $self = shift;
	my $ccv_query_log = shift;
	
	my $_REPORT_LOG_ = $self->get_report_log_file();
	my $_H_REPORT_LOG_ = undef;
    if (!open($_H_REPORT_LOG_, ">>", $_REPORT_LOG_)) {
		return;
	}  
	
    print $_H_REPORT_LOG_  $ccv_query_log;
    close($_H_REPORT_LOG_);
}

sub format_time() {
    my $self = shift;

    my $time = time();
    #  0    1    2     3     4    5     6     7     8
    # ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time); 
    my @T = gmtime($time);
    $time = sprintf("%4d-%02d-%02d+%02d%02d%02d", 
                        $T[5] + 1900,
                        $T[4] + 1,
                        $T[3],
                        $T[2],
                        $T[1],
                        $T[0]);
    
    my $friendly_time = sprintf("%4d-%02d-%02d %02d:%02d:%02d", 
                        $T[5] + 1900,
                        $T[4] + 1,
                        $T[3],
                        $T[2],
                        $T[1],
                        $T[0]); 
                                           
    $self->{'time'} = $time;
    $self->{'friendly_time'} = $friendly_time;
    $self->split_time();
}

sub split_time() {
    my $self = shift; 
    
    my $time = $self->{'time'};
    $time =~ m/(.*)\+(.*)/;                   
    $self->{'date'} = $1;
    $self->{'serial'} = $2;
    
    my $friendly_time = $self->{'date'} . " " 
                . substr($self->{'serial'}, 0, 2) . ":"
                . substr($self->{'serial'}, 2, 2) . ":"
                . substr($self->{'serial'}, 4, 2);
                                           
    $self->{'friendly_time'} = $friendly_time;       
}

sub read_whole_file() {
    my $self = shift;
    my $file = shift;
    if (!open(INPUT, "<", $file)) {
        return undef;   
    }
    
    my $old = $/;
    undef $/;
    my $content = <INPUT>;
    close INPUT;
    $/ = $old;
    
    return $content;
}

sub read_file() {
    my $self = shift;
    my $file = shift;
    my $begin = shift;
    my $len = shift;
    
    if (!open(INPUT, "<", $file)) {
        return undef;   
    }
    seek(INPUT, $begin, 0);
    
    my $content = "";
    my $a_len = read(INPUT, $content, $len);
    close INPUT;

    return $content;
}

sub get_module_cvsroot() {
    my $self        = shift;
    my $mInfo	    = shift;
    
    my $cvs_username    = $mInfo->{username};
    my $cvs_password    = $mInfo->{password};
    my $cvs_server      = $mInfo->{server};
    my $cvs_repository  = $mInfo->{repository};
    my $cvs_mode = $mInfo->{access_mode};
    
    return $self->get_cvsroot($cvs_username, $cvs_password, $cvs_server, $cvs_repository, $cvs_mode);
}

sub getSvnModuleOperatedPath() {
    my $self        = shift;
    my $mInfo	    = shift;
    my $revsInfo    = shift;
    
	my $operatedPath = $mInfo->{trunk_directory};
	
	if ($revsInfo->{Flag}->{IsTrunk} || $revsInfo->{Flag}->{OnTrunk}) {
		$operatedPath = $mInfo->{trunk_directory};
	} else {
		$operatedPath = sprintf($mInfo->{branch_directory}, $revsInfo->{Base})
	}
	
	return $operatedPath;
}

sub get_svn_module_url() {
    my $self        = shift;
    my $mInfo	    = shift;
    my $rev 		= shift;
    my $revType		= shift;
	
	my $revsInfo = $self->getSvnLogRevsInfo($rev);
	
	my $url = "";
	my $moduleOperatedPath = $mInfo->{trunk_directory};
	
	if (defined($revType)) {
		if ($revType eq "branch") {
			$moduleOperatedPath = sprintf($mInfo->{branch_directory}, $rev);
		} elsif ($revType eq "tag") {
			$moduleOperatedPath = sprintf($mInfo->{tag_directory}, $rev);
		}
	} else {
		$moduleOperatedPath = $self->getSvnModuleOperatedPath($mInfo, $revsInfo);		
	}

	
    if ($mInfo->{access_mode} eq "file") {
		$url = sprintf("file://%s",
					$moduleOperatedPath);
    } else { #svn, svn+ssh, http, https
		$url = sprintf("%s://%s/%s",
					$mInfo->{access_mode},
					$mInfo->{server},
					$moduleOperatedPath);       		
    }

    $url =~ s|([^:])[\/]{2,}|$1\/|g;
    return $url;
}

sub getCvsLogRevs() {
    my $self = shift;
    my $revs = shift;
    
    my $atPos = index($revs, "\@");
    if ($atPos == -1) {
    	return $revs;
    } else {
    	return substr($revs, 0, $atPos);	
    }
}

sub getSvnLogRevsInfo() {
    my $self = shift;
    my $revs = shift;	
	
	my $info = {
		Revs => $revs,
		Flag => {
			IsTrunk => 0,	
			IsBranch => 0,
			OnTrunk => 0,
			OnBranch =>0
		},
		
		Base => $revs
	};
	
	if ($revs =~ m/^(\d+:\d+)\@(.*)$/) {#123:456@T27L10N_FR23
		my $revsScale = $1;
		my $onRev = $2;

		if ($onRev =~ m/^(|TRUNK)$/i) {
			$info->{Flag}->{OnTrunk} = 1;
			$info->{Base} = "TRUNK";
		} else {
			$info->{Flag}->{OnBranch} = 1;
			$info->{Base} = $onRev;
		}
		
		$info->{Revs} = $revsScale;
	} elsif ($revs =~ m/^(\d+:\d+)$/) {
		$info->{Flag}->{OnTrunk} = 1;
		$info->{Base} = "TRUNK";
	} elsif ($revs =~ m/^(TRUNK|MAIN)$/i) {
		$info->{Flag}->{IsTrunk} = 1;
		$info->{Base} = "TRUNK";
	} else {
		$info->{Flag}->{IsBranch} = 1;
	}
	
	return $info;
}

sub get_svn_file_url() {
    my $self        = shift;
    my $mInfo	    = shift;
    my $file 		= shift;
	
	my $url = '';
    if ($mInfo->{access_mode} eq "file") {
		$url = sprintf("file://%s/%s",
					$mInfo->{repository},
					$file);
    } else { #svn, svn+ssh, http, https
		$url = sprintf("%s://%s/%s/%s",
					$mInfo->{access_mode},
					$mInfo->{server},
					$mInfo->{repository},
					$file);       		
    }

    $url =~ s|([^:])[\/]{2,}|$1\/|g;
    return $url;
}

sub get_co_svn_file_cmd() {
    my $self        = shift;
    my $mInfo	    = shift;
    my $file 		= shift;
    my $rev			= shift;
	
	return sprintf("svn cat --non-interactive --username \"%s\" --password \"%s\" -r %s \"%s\"",
		$mInfo->{username},
		$mInfo->{password},
		$rev,
		$self->get_svn_file_url($mInfo, $file)
	);
}

sub get_df_svn_file_cmd() {
    my $self        = shift;
    my $mInfo	    = shift;
    my $file 		= shift;
    my $rev			= shift;
    
	return sprintf("svn diff --non-interactive --username \"%s\" --password \"%s\" -c %s \"%s\"",
		$mInfo->{username},
		$mInfo->{password},
		$rev,
		$self->get_svn_file_url($mInfo, $file)
	);
}

sub get_cvsroot() {
    my $self            = shift;
    my $cvs_username    = shift;
    my $cvs_password    = shift;
    my $cvs_server      = shift;
    my $cvs_repository  = shift;
    my $cvs_mode = shift;
    
    my $cvsroot = "";
    if (!$cvs_mode || $cvs_mode eq "pserver") {
    	$cvsroot = sprintf(":pserver:%s:%s@%s:%s",
                    $cvs_username,
                    $cvs_password,
                    $cvs_server,
                    $cvs_repository);
	} else {
    	$cvsroot = sprintf(":ext:%s@%s:%s",
                    $cvs_username,
                    $cvs_server,
                    $cvs_repository);		
	}                    
                    
    return $cvsroot;   
}

sub get_module_cvsroot_without_uid() {
    my $self            = shift;
    my $module_info	    = shift;
    
    my $cvsroot = sprintf(":pserver@%s:%s",
                    $module_info->{server},
                    $module_info->{repository}); 
                    
    return $cvsroot;   
}

sub write_file() {
    my $self = shift;
    my $file = shift;
    my $content = shift;
    my $mode = shift;
    
    if (!defined($mode) || $mode eq "") {
    	$mode = ">";
    }
    my $H;
    if (!open($H, $mode, $file)) {
       return 1;
    }
    
    print $H $content; 
    close($H);
}

sub debug() {
    my $self            = shift;    
    my $info            = shift;
    
    my $old = umask(0);
    my $DEBUG;
    if (!open($DEBUG, ">>", "/tmp/CCV-DEBUG")) {
       return 1;
    }
    print $DEBUG $info . "\n";
    close($DEBUG);     
    umask($old);
    return 0;
}

sub getHtmlReportURL() {
    my $self = shift;
    my $reportMode = shift;
    my $revsDirUnderT_SNAP = shift;	
	
	my $htmlReportURL = "";
    if ($reportMode == 0) {
	    $htmlReportURL = $self->get_branch_html_report_url($revsDirUnderT_SNAP);
	} else {
	    $htmlReportURL = $self->get_rdiff_html_report_url($revsDirUnderT_SNAP);
	}
	
	return $htmlReportURL;
}

sub getPlainReportURL() {
    my $self = shift;

	return $self->get_brief_report_url();
}

sub get_config_files() {
	my $self = shift;
	
    my $it = new File::Iterator(DIR     => "config",
                                RECURSE => 0,
                                FILTER  => sub { $_[0] =~ /\.xml$/});
    my $files = [];
    while (my $file = $it->next()) {
        $file =~ s/.*[\/\\]//;
        push(@{$files}, $file);
    }    
    $self->{CFG_FILES} = $files;
    
    $self->get_default_config();
}

sub isValidCfg() {
	my $self = shift;
	my $cfgFile = shift;
	
	for (my $i = 0; $i <= $#{$self->{CFG_FILES}}; $i++) {
		if ($self->{CFG_FILES}->[$i] eq $cfgFile) {
			return 1;
		}
	}
	
	return 0;
}

sub get_default_config() {
	my $self = shift;
	
	my $default = $self->{CFG_FILES}->[0];
	
	my $joinCfgs = join(",", @{$self->{CFG_FILES}});
	
	if (index(",$joinCfgs,", ",config.xml,") != -1) {
		$default = "config.xml";
	} elsif (index(",$joinCfgs,", ",example.xml,") != -1) {
		$default = "example.xml";
	}

	$self->{DEFAULT_CFG} = $default;
}

sub getPmsFile() {
	my $self = shift;
	
	
	return "operate/" . $self->{'date'} . "/" . $self->{'serial'} . "/pms.ccv" 
}

sub getSvnModuleRevFullPath() {
	my $self = shift;
	my $mInfo = shift;
	my $pms = shift;
	my $revBase = $self->getSvnRevBase($pms);
	
	my $revFullPath = ($revBase eq 'trunk') ? $mInfo->{trunk_directory} : (($revBase eq 'branch') ? sprintf($mInfo->{branch_directory}, $pms->{rev}) :  sprintf($mInfo->{tag_directory}, $pms->{rev}));
	return $revFullPath;
}


sub isTrunk() {
	my $self = shift;
	my $pms = shift;

	return $pms->{rev} eq 'MAIN' || $pms->{rev} eq 'TRUNK';
}

sub getSvnRevBase() {
	my $self = shift;
	my $pms = shift;

	return $self->isTrunk($pms) ? 'trunk' : 'branch';
}

sub getSvnModuleLogParsedInfoYamlFile() {
	my $self = shift;
	my $pms = shift;
	my $mid = shift;
	
	return "operate/$self->{date}/$self->{serial}/$pms->{rev}/$mid/$self->{SVN_LOG_PARSED_INFO_FILE_NAME}";
}

sub getSvnMoudleAllRevsDFFile() {
	my $self = shift;
	my $pms = shift;
	my $mid = shift;
	
	return "operate/$self->{date}/$self->{serial}/$pms->{rev}/$mid/all.revs.df";    
}

sub getSvnMoudleInitRevFileLocation() {
	my $self = shift;
	my $pms = shift;
	my $mid = shift;
	
	return "operate/$self->{date}/$self->{serial}/$pms->{rev}/$mid/rev_src/init";    
}

sub localReportPath2WebPath() {
	my $self = shift;
	my $path = shift;
	
	return '/ccv/' . substr($path, length('web/'));	
}


sub localOperatePath2WebPath() {
	my $self = shift;
	my $path = shift;
	
	return '/ccv/' . $path;	
}

#===============================================================================
#
# END of the module.
#
#===============================================================================
1;
__END__
